/**
 * AI诊断后端API服务
 * 处理大模型请求和响应，提供安全的API接口
 */

require('dotenv').config();
const express = require('express');
const axios = require('axios');
const cors = require('cors');
const rateLimit = require('express-rate-limit');
const SecurityManager = require('./security');

const app = express();
const PORT = process.env.PORT || 3001;

// 初始化安全管理器
const securityManager = new SecurityManager();

// 中间件配置
app.use(cors({
    origin: function (origin, callback) {
        if (!origin || securityManager.validateOrigin(origin)) {
            callback(null, true);
        } else {
            callback(new Error('不允许的请求来源'));
        }
    },
    credentials: true
}));

app.use(express.json({ limit: '1mb' })); // 限制请求体大小

// 请求日志中间件
app.use((req, res, next) => {
    const requestId = securityManager.generateRequestId();
    req.requestId = requestId;
    
    console.log(`[${new Date().toISOString()}] ${req.method} ${req.path} - ID: ${requestId} - IP: ${req.ip}`);
    next();
});

// 速率限制配置
const limiter = rateLimit({
    windowMs: parseInt(process.env.RATE_LIMIT_WINDOW_MS) || 15 * 60 * 1000, // 15分钟
    max: parseInt(process.env.RATE_LIMIT_MAX_REQUESTS) || 100, // 每个IP最多100次请求
    message: {
        success: false,
        error: '请求过于频繁，请稍后再试'
    },
    keyGenerator: (req) => req.ip // 基于IP进行限制
});

app.use(limiter);

// 医疗知识库
const MEDICAL_KNOWLEDGE_BASE = {
    commonSymptoms: {
        '头痛': ['偏头痛', '紧张性头痛', '高血压', '感冒'],
        '发热': ['上呼吸道感染', '流感', '肺炎', '病毒感染'],
        '咳嗽': ['支气管炎', '肺炎', '哮喘', '感冒'],
        '乏力': ['贫血', '低血糖', '睡眠不足', '慢性疲劳'],
        '恶心': ['胃炎', '食物中毒', '晕车', '早孕反应'],
        '腹泻': ['肠胃炎', '食物中毒', '消化不良', '肠道感染']
    },
    emergencySymptoms: [
        '胸痛', '呼吸困难', '意识模糊', '剧烈头痛',
        '持续高热', '严重呕吐', '便血', '抽搐'
    ]
};

/**
 * 构建医疗诊断提示词
 */
function buildMedicalPrompt(symptoms, additionalInfo = '') {
    const symptomList = Array.isArray(symptoms) ? symptoms.join(', ') : symptoms;
    
    return `你是一个专业的医疗AI助手。请根据以下症状信息进行初步诊断分析：

患者症状：${symptomList}
${additionalInfo ? `附加信息：${additionalInfo}` : ''}

请按照以下格式提供专业的诊断建议：
1. 可能的疾病分析（按可能性排序）
2. 建议的检查项目
3. 生活建议和注意事项
4. 是否需要立即就医

请用中文回答，保持专业、准确、谨慎的态度。注意：这只是初步建议，不能替代专业医生的诊断。`;
}

/**
 * 调用OpenAI GPT模型
 */
async function callOpenAI(prompt) {
    const apiKey = securityManager.apiKeys.get('openai');
    if (!apiKey) {
        throw new Error('OpenAI API密钥未配置');
    }

    try {
        const response = await axios.post('https://api.openai.com/v1/chat/completions', {
            model: 'gpt-3.5-turbo',
            messages: [
                {
                    role: 'system',
                    content: '你是一个专业的医疗AI助手，请提供准确、谨慎的医疗建议。'
                },
                {
                    role: 'user',
                    content: prompt
                }
            ],
            temperature: 0.7,
            max_tokens: 1000
        }, {
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${apiKey}`
            },
            timeout: 30000
        });

        return response.data.choices[0].message.content;
    } catch (error) {
        console.error('OpenAI API调用失败:', error.response?.data || error.message);
        throw new Error('OpenAI服务暂时不可用');
    }
}

/**
 * 调用Claude模型
 */
async function callClaude(prompt) {
    const apiKey = securityManager.apiKeys.get('anthropic');
    if (!apiKey) {
        throw new Error('Claude API密钥未配置');
    }

    try {
        const response = await axios.post('https://api.anthropic.com/v1/messages', {
            model: 'claude-3-sonnet-20240229',
            max_tokens: 1000,
            temperature: 0.7,
            messages: [
                {
                    role: 'user',
                    content: prompt
                }
            ]
        }, {
            headers: {
                'Content-Type': 'application/json',
                'x-api-key': apiKey,
                'anthropic-version': '2023-06-01'
            },
            timeout: 30000
        });

        return response.data.content[0].text;
    } catch (error) {
        console.error('Claude API调用失败:', error.response?.data || error.message);
        throw new Error('Claude服务暂时不可用');
    }
}

/**
 * 调用文心一言模型
 */
async function callErnie(prompt) {
    const apiKey = securityManager.apiKeys.get('baidu');
    if (!apiKey) {
        throw new Error('文心一言API密钥未配置');
    }

    try {
        // 首先获取access_token
        const [clientId, clientSecret] = apiKey.split(':');
        const tokenResponse = await axios.post(`https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=${clientId}&client_secret=${clientSecret}`);
        const accessToken = tokenResponse.data.access_token;

        const response = await axios.post(`https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions?access_token=${accessToken}`, {
            messages: [
                {
                    role: 'user',
                    content: prompt
                }
            ],
            temperature: 0.7,
            max_tokens: 1000
        }, {
            headers: {
                'Content-Type': 'application/json'
            },
            timeout: 30000
        });

        return response.data.result;
    } catch (error) {
        console.error('文心一言API调用失败:', error.response?.data || error.message);
        throw new Error('文心一言服务暂时不可用');
    }
}

/**
 * 分类API错误类型
 */
function classifyAPIError(error) {
    const message = error.message.toLowerCase();
    
    if (message.includes('timeout') || message.includes('timed out')) {
        return 'timeout';
    } else if (message.includes('rate limit') || message.includes('too many requests')) {
        return 'rate_limit';
    } else if (message.includes('authentication') || message.includes('unauthorized') || message.includes('invalid api key')) {
        return 'authentication';
    } else if (message.includes('quota') || message.includes('exceeded')) {
        return 'quota_exceeded';
    } else if (message.includes('network') || message.includes('connection')) {
        return 'network_error';
    } else if (message.includes('internal server error') || message.includes('server error')) {
        return 'server_error';
    } else {
        return 'unknown_error';
    }
}

/**
 * 本地模拟模型（降级方案）
 */
async function callLocalModel(symptoms, additionalInfo = '') {
    await new Promise(resolve => setTimeout(resolve, 2000));
    
    const symptomList = Array.isArray(symptoms) ? symptoms.join(', ') : symptoms;
    const symptomLower = symptomList.toLowerCase();
    
    // 基于医疗知识库的智能匹配
    let matchedConditions = [];
    
    // 检查常见症状
    for (const [symptom, conditions] of Object.entries(MEDICAL_KNOWLEDGE_BASE.commonSymptoms)) {
        if (symptomLower.includes(symptom)) {
            matchedConditions = matchedConditions.concat(conditions);
        }
    }
    
    // 去重
    matchedConditions = [...new Set(matchedConditions)];
    
    // 检查紧急症状
    const hasEmergency = MEDICAL_KNOWLEDGE_BASE.emergencySymptoms.some(symptom => 
        symptomLower.includes(symptom)
    );
    
    if (hasEmergency) {
        return `基于您描述的症状"${symptomList}"，AI初步分析如下：

⚠️ **紧急情况警告**：您的症状可能涉及紧急医疗情况！

1. 可能的疾病分析：
   - 需要立即医疗评估的紧急情况
   - 可能存在严重的心血管、呼吸系统或神经系统问题

2. 建议检查项目：
   - 立即前往急诊科
   - 心电图检查
   - 血常规和生化检查
   - 影像学检查

3. 生活建议：
   - 立即停止所有活动
   - 保持安静，等待医疗救助
   - 不要自行驾车前往医院

4. 就医建议：
   - **立即拨打急救电话或前往最近医院的急诊科**
   - 这些症状需要专业医生的紧急评估`;
    }
    
    if (matchedConditions.length > 0) {
        return `基于您描述的症状"${symptomList}"，AI初步分析如下：

1. 可能的疾病分析：
   ${matchedConditions.map((condition, index) => `   - ${condition}（可能性${80 - index * 10}%）`).join('\n')}

2. 建议检查项目：
   - 基础体格检查
   - 血常规检查
   - 相关专科检查

3. 生活建议：
   - 注意休息，保证充足睡眠
   - 均衡饮食，补充营养
   - 适当进行轻度运动

4. 就医建议：
   - 建议尽快就医进行专业诊断
   - 如症状持续或加重，请及时复诊`;
    } else {
        return `基于您描述的症状"${symptomList}"，AI初步分析如下：

1. 可能的疾病分析：
   - 需要更多症状信息进行准确判断
   - 建议详细描述症状的持续时间、严重程度等

2. 建议检查项目：
   - 基础体格检查
   - 根据具体症状选择相应专科检查

3. 生活建议：
   - 注意休息，观察症状变化
   - 记录症状发展情况

4. 就医建议：
   - 建议咨询专业医生进行详细诊断
   - 如果症状持续或加重，请及时就医`;
    }
}

/**
 * AI诊断API端点
 */
app.post('/api/ai-diagnosis', async (req, res) => {
    try {
        const requestId = req.requestId;
        const clientIP = req.ip;
        
        // 检查速率限制
        if (!securityManager.checkRateLimit(clientIP, 'ai-diagnosis')) {
            securityManager.logSecurityEvent('RATE_LIMIT_EXCEEDED', {
                requestId,
                clientIP,
                endpoint: 'ai-diagnosis'
            });
            
            return res.status(429).json({
                success: false,
                error: '请求过于频繁，请稍后再试'
            });
        }
        
        const { symptoms, additionalInfo = '', model = 'local' } = req.body;
        
        // 验证输入
        const validation = securityManager.validateSymptoms(symptoms);
        if (!validation.valid) {
            securityManager.logSecurityEvent('INVALID_INPUT', {
                requestId,
                clientIP,
                error: validation.error
            });
            
            return res.status(400).json({
                success: false,
                error: validation.error
            });
        }
        
        console.log(`[${requestId}] 收到AI诊断请求 - 模型: ${model}, 症状: ${symptoms.substring(0, 50)}...`);
        
        let result;
        const prompt = buildMedicalPrompt(symptoms, additionalInfo);
        
        try {
            // 根据选择的模型调用相应的API
            switch (model) {
                case 'openai':
                    result = await callOpenAI(prompt);
                    break;
                case 'claude':
                    result = await callClaude(prompt);
                    break;
                case 'ernie':
                    result = await callErnie(prompt);
                    break;
                case 'local':
                default:
                    result = await callLocalModel(symptoms, additionalInfo);
                    break;
            }
            
            securityManager.logSecurityEvent('DIAGNOSIS_SUCCESS', {
                requestId,
                clientIP,
                model,
                symptomsLength: symptoms.length
            });
            
            res.json({
                success: true,
                diagnosis: result,
                model: model,
                timestamp: new Date().toISOString(),
                requestId: requestId
            });
            
        } catch (apiError) {
            console.error(`[${requestId}] ${model} API调用失败，使用本地模型降级:`, apiError);
            
            // 分类错误类型
            const errorType = classifyAPIError(apiError);
            
            securityManager.logSecurityEvent('API_FALLBACK', {
                requestId,
                clientIP,
                model,
                error: apiError.message,
                errorType: errorType
            });
            
            // 根据错误类型选择降级策略
            let fallbackResult;
            try {
                fallbackResult = await callLocalModel(symptoms, additionalInfo);
            } catch (fallbackError) {
                // 如果本地模型也失败，返回错误信息
                securityManager.logSecurityEvent('FALLBACK_FAILED', {
                    requestId,
                    clientIP,
                    model,
                    error: fallbackError.message
                });
                
                return res.status(500).json({
                    success: false,
                    error: 'AI诊断服务暂时不可用，请稍后重试',
                    errorType: 'service_unavailable',
                    timestamp: new Date().toISOString(),
                    requestId: requestId
                });
            }
            
            res.json({
                success: true,
                diagnosis: fallbackResult,
                model: 'local',
                fallback: true,
                fallbackReason: errorType,
                timestamp: new Date().toISOString(),
                requestId: requestId
            });
        }
        
    } catch (error) {
        console.error(`[${req.requestId}] AI诊断处理错误:`, error);
        
        securityManager.logSecurityEvent('INTERNAL_ERROR', {
            requestId: req.requestId,
            clientIP: req.ip,
            error: error.message
        });
        
        res.status(500).json({
            success: false,
            error: 'AI诊断服务暂时不可用，请稍后重试',
            requestId: req.requestId
        });
    }
});

/**
 * 健康检查端点
 */
app.get('/api/health', (req, res) => {
    res.json({
        status: 'healthy',
        service: 'AI Diagnosis API',
        timestamp: new Date().toISOString(),
        version: '1.0.0'
    });
});

/**
 * 获取支持的模型列表
 */
app.get('/api/models', (req, res) => {
    const availableModels = securityManager.getAvailableModels();
    
    res.json({
        models: availableModels,
        timestamp: new Date().toISOString(),
        requestId: req.requestId
    });
});

// 启动服务器
app.listen(PORT, () => {
    console.log(`AI诊断API服务运行在端口 ${PORT}`);
    console.log(`健康检查: http://localhost:${PORT}/api/health`);
    console.log(`模型列表: http://localhost:${PORT}/api/models`);
});

module.exports = app;